classdef DookuSynthesizer < handle
    %%DOOKUZYNTHESIZER Dooku Synthesizer main window GUI class
    
    properties
        % Figure variables
        hfig;
        handles;
        
        % Track variables
        track;
        trackInd;
        trackFileName;
        trackFilePath;
        
        % Song variables
        song;
        songName;
        songVolume;
        songReverbInd;
        songReverbSet; %Struct
    end
    
    methods
        
        function obj = MainWindow
            % Figure Load
            obj.hfig = hgload('principalGUI.fig');
            obj.handles = guihandles(obj.hfig);
            
            % Background Image
            img = imread('Black3.jpg');
            image(img, 'Parent', obj.handles.background);
            
            % Load variables
            obj.loadVariables();
            
            % Callbacks Definitions
            set(obj.handles.mainMenu, 'CloseRequestFcn', @(src, event) closeProgram(obj, src, event));
            set(obj.handles.track_add, 'Callback', @(src, event) newTrackSelect(obj, src, event));
            set(obj.handles.track_input, 'Callback', @(src, event) inputFileSelect(obj, src, event));
            set(obj.handles.trackList, 'Callback', @(src, event) trackListSelect(obj, src, event));
            set(obj.handles.track_remove, 'Callback', @(src, event) trackRemove(obj, src, event));
            set(obj.handles.instrMenu, 'Callback', @(src, event) instrumentSelect(obj, src, event));
            set(obj.handles.track_instrset, 'Callback', @(src, event) instrumentSettings(obj, src, event));
            set(obj.handles.track_addeffect, 'Callback', @(src, event) addEffectSelect(obj, src, event));
            set(obj.handles.effectsList, 'Callback', @(src, event) effectListSelect(obj, src, event));
            set(obj.handles.track_effectset, 'Callback', @(src, event) effectSettings(obj, src, event));
            set(obj.handles.track_effectrem, 'Callback', @(src, event) effectRemove(obj, src, event));
            set(obj.handles.song_new, 'Callback', @(src, event) newSong(obj, src, event));
            set(obj.handles.song_save, 'Callback', @(src, event) saveSong(obj, src, event));
            set(obj.handles.song_load, 'Callback', @(src, event) loadSong(obj, src, event));
            set(obj.handles.reverbMenu, 'Callback', @(src, event) reverbSelect(obj, src, event));
            set(obj.handles.song_revset, 'Callback', @(src, event) reverbSettings(obj, src, event));
            bg_image = imread('play.png');
            set(obj.handles.track_play, 'Callback', @(src, event) playTrack(obj, src, event), 'CData', bg_image);
            set(obj.handles.song_play, 'Callback', @(src, event) playSong(obj, src, event), 'CData', bg_image);
            bg_image = imread('stop.png');
            set(obj.handles.track_stop, 'Callback', @(src, event) stopTrack(obj, src, event), 'CData', bg_image);
            set(obj.handles.song_stop, 'Callback', @(src, event) stopSong(obj, src, event), 'CData', bg_image);
            set(obj.handles.track_volslider, 'Callback', @(src, event) volumeTrack(obj, src, event));
            set(obj.handles.song_volslider, 'Callback', @(src, event) volumeSong(obj, src, event));
        end
                
        function obj = closeProgram(obj, ~, ~)
            % Save variables
            try
                autosave.track_name = get(obj.handles.track_name, 'String');
                autosave.trackFileName = obj.trackFileName;
                autosave.trackFilePath = obj.trackFilePath;
                autosave.track = obj.track;
                autosave.trackInd = obj.trackInd;
                save('autosave.mat', '-struct', 'autosave');
            catch
            end
            
            % Close Figure
            delete(obj.hfig);
            clear obj.hfig;
        end
        
        function loadVariables(obj)
            % Load variables
            if exist('autosave.mat', 'file')
                try
                    autosave = load('autosave.mat');
                    set(obj.handles.track_name, 'String', autosave.track_name);
                    obj.trackFileName = autosave.trackFileName;
                    if ~isempty(obj.trackFileName)
                        set(obj.handles.track_inputname, 'String', obj.trackFileName);
                    end
                    obj.trackFilePath = autosave.trackFilePath;
                    obj.track = autosave.track;
                    obj.trackInd = autosave.trackInd;
                    obj.refreshTrackList();
                catch
                end
            end
        end
        
        function obj = newTrackSelect(obj, ~, ~)
            trackNameStr = get(obj.handles.track_name, 'String');
            if ~isempty(obj.trackFileName) && ~isempty(trackNameStr)
                obj.track{end+1} = Track(trackNameStr, obj.trackFileName);
                obj.trackInd = length(obj.track);
                obj.refreshTrackList();
                set(obj.handles.track_name, 'String', '');
            else
                if isempty(obj.trackFileName)
                    errordlg('There is no MID or WAV file selected', 'Inconsistent error');
                    return
                end
                if isempty(trackNameStr)
                    errordlg('Track name cannot be empty', 'Inconsistent error');
                    return
                end  
            end
        end
        
        function refreshTrackList(obj)
            listStr = '';
            for k = 1:length(obj.track)
                listStr = [listStr; {obj.track{k}.name}]; %#ok<AGROW>
            end
            set(obj.handles.trackList, 'String', listStr, 'Value', obj.trackInd);
            obj.refreshTrack();
        end
        
        function refreshTrack(obj)
            if ~isempty(obj.track)
                set(obj.handles.track_volnum, 'String', [num2str(100*obj.track{obj.trackInd}.volume), '%']);
                set(obj.handles.track_volslider, 'Value', obj.track{obj.trackInd}.volume);
                set(obj.handles.instrMenu, 'Value', obj.track{obj.trackInd}.instrInd);
                obj.refreshEffectsList();
            end
        end
        
        function obj = inputFileSelect(obj, ~, ~)
            [obj.trackFileName, trackPathName] = uigetfile({'*.mid'});% *.wav'});
            obj.trackFilePath = [trackPathName, obj.trackFileName];
            set(obj.handles.track_inputname, 'String', obj.trackFileName);
        end
        
        function obj = trackListSelect(obj, ~, ~)
            obj.trackInd = get(obj.handles.trackList, 'Value');
            obj.refreshTrack();
        end
        
        function obj = trackRemove(obj, ~, ~)
            if ~isempty(obj.track)
                obj.track(:, obj.trackInd) = [];
                if obj.trackInd > length(obj.track)
                    obj.trackInd = obj.trackInd - 1;
                end
                obj.refreshTrackList();
            end
        end
        
        function obj = instrumentSelect(obj, ~, ~)
            obj.track{obj.trackInd}.instrInd = get(obj.handles.instrMenu, 'Value');
        end
        
        function obj = instrumentSettings(obj, ~, ~)
            disp('Instrument Settings');
        end
        
        function obj = addEffectSelect(obj, ~, ~)
            if ~isempty(obj.track)
                effectsName = get(obj.handles.effectMenu, 'String');
                effectSelectInd = get(obj.handles.effectMenu, 'Value');
                obj.track{obj.trackInd}.effect{end+1} = Effect(effectsName(effectSelectInd));
                obj.track{obj.trackInd}.effectInd = length(obj.track{obj.trackInd}.effect);
                obj.refreshEffectsList();
            end
        end
        
        function refreshEffectsList(obj)
            listStr = '';
            for k = 1:length(obj.track{obj.trackInd}.effect)
                listStr = [listStr; obj.track{obj.trackInd}.effect{k}.name]; %#ok<AGROW>
            end
            set(obj.handles.effectsList, 'String', listStr, 'Value', obj.track{obj.trackInd}.effectInd);
        end
        
        function obj = effectListSelect(obj, ~, ~)
            obj.track{obj.trackInd}.effectInd = get(obj.handles.effectsList, 'Value');
        end
        
        function obj = effectSettings(obj, ~, ~)
            disp('Effect Settings');
        end

        function obj = effectRemove(obj, ~, ~)
            if ~isempty(obj.track{obj.trackInd})
                obj.track{obj.trackInd}.effect(:, obj.track{obj.trackInd}.effectInd) = [];
                if obj.track{obj.trackInd}.effectInd > length(obj.track{obj.trackInd}.effect)
                    obj.track{obj.trackInd}.effectInd = obj.track{obj.trackInd}.effectInd - 1;
                end
                obj.refreshEffectsList();
            end
        end
        
        function obj = newSong(obj, ~, ~)
            disp('New Song');
        end
        
        function obj = saveSong(obj, ~, ~)
            disp('Save Song');
        end
        
        function obj = loadSong(obj, ~, ~)
            disp('Load Song');
        end
        
        function obj = reverbSelect(obj, ~, ~)
            disp('Reverb Select');
        end
        
        function obj = reverbSettings(obj, ~, ~)
            disp('Reverb Settings');
        end
        
        function obj = playTrack(obj, ~, ~)
            disp('Play Track');
        end
        
        function obj = stopTrack(obj, ~, ~)
            disp('Stop Track');
        end
        
        function obj = volumeTrack(obj, src, ~)
            set(obj.handles.track_volnum, 'String', [num2str(100*get(src, 'Value')), '%']);
            obj.track{obj.trackInd}.volume = get(src, 'Value');
        end
        
        function obj = playSong(obj, ~, ~)
            disp('Play Song');
        end
        
        function obj = stopSong(obj, ~, ~)
            disp('Stop Song');
        end
        
        function obj = volumeSong(obj, src, ~)
            set(obj.handles.song_volnum, 'String', [num2str(100*get(src, 'Value')), '%']);
        end
        
    end
end